home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / Mail / cmd2.c < prev    next >
C/C++ Source or Header  |  1990-02-08  |  9KB  |  501 lines

  1. /*
  2.  * Copyright (c) 1980 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. #ifndef lint
  19. static char sccsid[] = "@(#)cmd2.c    5.12 (Berkeley) 2/6/89";
  20. #endif /* not lint */
  21.  
  22. #include "rcv.h"
  23. #include <sys/wait.h>
  24.  
  25. /*
  26.  * Mail -- a mail program
  27.  *
  28.  * More user commands.
  29.  */
  30.  
  31. /*
  32.  * If any arguments were given, go to the next applicable argument
  33.  * following dot, otherwise, go to the next applicable message.
  34.  * If given as first command with no arguments, print first message.
  35.  */
  36.  
  37. next(msgvec)
  38.     int *msgvec;
  39. {
  40.     register struct message *mp;
  41.     register int *ip, *ip2;
  42.     int list[2], mdot;
  43.  
  44.     if (*msgvec != NULL) {
  45.  
  46.         /*
  47.          * If some messages were supplied, find the 
  48.          * first applicable one following dot using
  49.          * wrap around.
  50.          */
  51.  
  52.         mdot = dot - &message[0] + 1;
  53.  
  54.         /*
  55.          * Find the first message in the supplied
  56.          * message list which follows dot.
  57.          */
  58.  
  59.         for (ip = msgvec; *ip != NULL; ip++)
  60.             if (*ip > mdot)
  61.                 break;
  62.         if (*ip == NULL)
  63.             ip = msgvec;
  64.         ip2 = ip;
  65.         do {
  66.             mp = &message[*ip2 - 1];
  67.             if ((mp->m_flag & MDELETED) == 0) {
  68.                 dot = mp;
  69.                 goto hitit;
  70.             }
  71.             if (*ip2 != NULL)
  72.                 ip2++;
  73.             if (*ip2 == NULL)
  74.                 ip2 = msgvec;
  75.         } while (ip2 != ip);
  76.         printf("No messages applicable\n");
  77.         return(1);
  78.     }
  79.  
  80.     /*
  81.      * If this is the first command, select message 1.
  82.      * Note that this must exist for us to get here at all.
  83.      */
  84.  
  85.     if (!sawcom)
  86.         goto hitit;
  87.  
  88.     /*
  89.      * Just find the next good message after dot, no
  90.      * wraparound.
  91.      */
  92.  
  93.     for (mp = dot+1; mp < &message[msgCount]; mp++)
  94.         if ((mp->m_flag & (MDELETED|MSAVED)) == 0)
  95.             break;
  96.     if (mp >= &message[msgCount]) {
  97.         printf("At EOF\n");
  98.         return(0);
  99.     }
  100.     dot = mp;
  101. hitit:
  102.     /*
  103.      * Print dot.
  104.      */
  105.  
  106.     list[0] = dot - &message[0] + 1;
  107.     list[1] = NULL;
  108.     return(type(list));
  109. }
  110.  
  111. /*
  112.  * Save a message in a file.  Mark the message as saved
  113.  * so we can discard when the user quits.
  114.  */
  115. save(str)
  116.     char str[];
  117. {
  118.  
  119.     return save1(str, 1, "save", saveignore);
  120. }
  121.  
  122. /*
  123.  * Copy a message to a file without affected its saved-ness
  124.  */
  125. copycmd(str)
  126.     char str[];
  127. {
  128.  
  129.     return save1(str, 0, "copy", saveignore);
  130. }
  131.  
  132. /*
  133.  * Save/copy the indicated messages at the end of the passed file name.
  134.  * If mark is true, mark the message "saved."
  135.  */
  136. save1(str, mark, cmd, ignore)
  137.     char str[];
  138.     char *cmd;
  139.     struct ignoretab *ignore;
  140. {
  141.     register int *ip;
  142.     register struct message *mp;
  143.     char *file, *disp;
  144.     int f, *msgvec;
  145.     FILE *obuf;
  146.  
  147.     msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec);
  148.     if ((file = snarf(str, &f)) == NOSTR)
  149.         return(1);
  150.     if (!f) {
  151.         *msgvec = first(0, MMNORM);
  152.         if (*msgvec == NULL) {
  153.             printf("No messages to %s.\n", cmd);
  154.             return(1);
  155.         }
  156.         msgvec[1] = NULL;
  157.     }
  158.     if (f && getmsglist(str, msgvec, 0) < 0)
  159.         return(1);
  160.     if ((file = expand(file)) == NOSTR)
  161.         return(1);
  162.     printf("\"%s\" ", file);
  163.     fflush(stdout);
  164.     if (access(file, 0) >= 0)
  165.         disp = "[Appended]";
  166.     else
  167.         disp = "[New file]";
  168.     if ((obuf = fopen(file, "a")) == NULL) {
  169.         perror(NOSTR);
  170.         return(1);
  171.     }
  172.     for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
  173.         mp = &message[*ip - 1];
  174.         touch(mp);
  175.         if (send(mp, obuf, ignore, NOSTR) < 0) {
  176.             perror(file);
  177.             fclose(obuf);
  178.             return(1);
  179.         }
  180.         if (mark)
  181.             mp->m_flag |= MSAVED;
  182.     }
  183.     fflush(obuf);
  184.     if (ferror(obuf))
  185.         perror(file);
  186.     fclose(obuf);
  187.     printf("%s\n", disp);
  188.     return(0);
  189. }
  190.  
  191. /*
  192.  * Write the indicated messages at the end of the passed
  193.  * file name, minus header and trailing blank line.
  194.  */
  195.  
  196. swrite(str)
  197.     char str[];
  198. {
  199.  
  200.     return save1(str, 1, "write", ignoreall);
  201. }
  202.  
  203. /*
  204.  * Snarf the file from the end of the command line and
  205.  * return a pointer to it.  If there is no file attached,
  206.  * just return NOSTR.  Put a null in front of the file
  207.  * name so that the message list processing won't see it,
  208.  * unless the file name is the only thing on the line, in
  209.  * which case, return 0 in the reference flag variable.
  210.  */
  211.  
  212. char *
  213. snarf(linebuf, flag)
  214.     char linebuf[];
  215.     int *flag;
  216. {
  217.     register char *cp;
  218.  
  219.     *flag = 1;
  220.     cp = strlen(linebuf) + linebuf - 1;
  221.  
  222.     /*
  223.      * Strip away trailing blanks.
  224.      */
  225.  
  226.     while (cp > linebuf && isspace(*cp))
  227.         cp--;
  228.     *++cp = 0;
  229.  
  230.     /*
  231.      * Now search for the beginning of the file name.
  232.      */
  233.  
  234.     while (cp > linebuf && !isspace(*cp))
  235.         cp--;
  236.     if (*cp == '\0') {
  237.         printf("No file specified.\n");
  238.         return(NOSTR);
  239.     }
  240.     if (isspace(*cp))
  241.         *cp++ = 0;
  242.     else
  243.         *flag = 0;
  244.     return(cp);
  245. }
  246.  
  247. /*
  248.  * Delete messages.
  249.  */
  250.  
  251. delete(msgvec)
  252.     int msgvec[];
  253. {
  254.     delm(msgvec);
  255.     return 0;
  256. }
  257.  
  258. /*
  259.  * Delete messages, then type the new dot.
  260.  */
  261.  
  262. deltype(msgvec)
  263.     int msgvec[];
  264. {
  265.     int list[2];
  266.     int lastdot;
  267.  
  268.     lastdot = dot - &message[0] + 1;
  269.     if (delm(msgvec) >= 0) {
  270.         list[0] = dot - &message[0] + 1;
  271.         if (list[0] > lastdot) {
  272.             touch(dot);
  273.             list[1] = NULL;
  274.             return(type(list));
  275.         }
  276.         printf("At EOF\n");
  277.     } else
  278.         printf("No more messages\n");
  279.     return(0);
  280. }
  281.  
  282. /*
  283.  * Delete the indicated messages.
  284.  * Set dot to some nice place afterwards.
  285.  * Internal interface.
  286.  */
  287.  
  288. delm(msgvec)
  289.     int *msgvec;
  290. {
  291.     register struct message *mp;
  292.     register *ip;
  293.     int last;
  294.  
  295.     last = NULL;
  296.     for (ip = msgvec; *ip != NULL; ip++) {
  297.         mp = &message[*ip - 1];
  298.         touch(mp);
  299.         mp->m_flag |= MDELETED|MTOUCH;
  300.         mp->m_flag &= ~(MPRESERVE|MSAVED|MBOX);
  301.         last = *ip;
  302.     }
  303.     if (last != NULL) {
  304.         dot = &message[last-1];
  305.         last = first(0, MDELETED);
  306.         if (last != NULL) {
  307.             dot = &message[last-1];
  308.             return(0);
  309.         }
  310.         else {
  311.             dot = &message[0];
  312.             return(-1);
  313.         }
  314.     }
  315.  
  316.     /*
  317.      * Following can't happen -- it keeps lint happy
  318.      */
  319.  
  320.     return(-1);
  321. }
  322.  
  323. /*
  324.  * Undelete the indicated messages.
  325.  */
  326.  
  327. undelete(msgvec)
  328.     int *msgvec;
  329. {
  330.     register struct message *mp;
  331.     register *ip;
  332.  
  333.     for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
  334.         mp = &message[*ip - 1];
  335.         touch(mp);
  336.         dot = mp;
  337.         mp->m_flag &= ~MDELETED;
  338.     }
  339.     return 0;
  340. }
  341.  
  342. /*
  343.  * Interactively dump core on "core"
  344.  */
  345.  
  346. core()
  347. {
  348.     int pid;
  349.     extern union wait wait_status;
  350.  
  351.     switch (pid = vfork()) {
  352.     case -1:
  353.         perror("fork");
  354.         return(1);
  355.     case 0:
  356.         abort();
  357.         _exit(1);
  358.     }
  359.     printf("Okie dokie");
  360.     fflush(stdout);
  361.     wait_child(pid);
  362.     if (wait_status.w_coredump)
  363.         printf(" -- Core dumped.\n");
  364.     else
  365.         printf(" -- Can't dump core.\n");
  366.     return 0;
  367. }
  368.  
  369. /*
  370.  * Clobber as many bytes of stack as the user requests.
  371.  */
  372. clobber(argv)
  373.     char **argv;
  374. {
  375.     register int times;
  376.  
  377.     if (argv[0] == 0)
  378.         times = 1;
  379.     else
  380.         times = (atoi(argv[0]) + 511) / 512;
  381.     clob1(times);
  382.     return 0;
  383. }
  384.  
  385. /*
  386.  * Clobber the stack.
  387.  */
  388. clob1(n)
  389. {
  390.     char buf[512];
  391.     register char *cp;
  392.  
  393.     if (n <= 0)
  394.         return;
  395.     for (cp = buf; cp < &buf[512]; *cp++ = 0xFF)
  396.         ;
  397.     clob1(n - 1);
  398. }
  399.  
  400. /*
  401.  * Add the given header fields to the retained list.
  402.  * If no arguments, print the current list of retained fields.
  403.  */
  404. retfield(list)
  405.     char *list[];
  406. {
  407.  
  408.     return ignore1(list, ignore + 1, "retained");
  409. }
  410.  
  411. /*
  412.  * Add the given header fields to the ignored list.
  413.  * If no arguments, print the current list of ignored fields.
  414.  */
  415. igfield(list)
  416.     char *list[];
  417. {
  418.  
  419.     return ignore1(list, ignore, "ignored");
  420. }
  421.  
  422. saveretfield(list)
  423.     char *list[];
  424. {
  425.  
  426.     return ignore1(list, saveignore + 1, "retained");
  427. }
  428.  
  429. saveigfield(list)
  430.     char *list[];
  431. {
  432.  
  433.     return ignore1(list, saveignore, "ignored");
  434. }
  435.  
  436. ignore1(list, tab, which)
  437.     char *list[];
  438.     struct ignoretab *tab;
  439.     char *which;
  440. {
  441.     char field[BUFSIZ];
  442.     register int h;
  443.     register struct ignore *igp;
  444.     char **ap;
  445.  
  446.     if (*list == NOSTR)
  447.         return igshow(tab, which);
  448.     for (ap = list; *ap != 0; ap++) {
  449.         istrcpy(field, *ap);
  450.         if (member(field, tab))
  451.             continue;
  452.         h = hash(field);
  453.         igp = (struct ignore *) calloc(1, sizeof (struct ignore));
  454.         igp->i_field = calloc((unsigned) strlen(field) + 1,
  455.             sizeof (char));
  456.         strcpy(igp->i_field, field);
  457.         igp->i_link = tab->i_head[h];
  458.         tab->i_head[h] = igp;
  459.         tab->i_count++;
  460.     }
  461.     return 0;
  462. }
  463.  
  464. /*
  465.  * Print out all currently retained fields.
  466.  */
  467. igshow(tab, which)
  468.     struct ignoretab *tab;
  469.     char *which;
  470. {
  471.     register int h;
  472.     struct ignore *igp;
  473.     char **ap, **ring;
  474.     int igcomp();
  475.  
  476.     if (tab->i_count == 0) {
  477.         printf("No fields currently being %s.\n", which);
  478.         return 0;
  479.     }
  480.     ring = (char **) salloc((tab->i_count + 1) * sizeof (char *));
  481.     ap = ring;
  482.     for (h = 0; h < HSHSIZE; h++)
  483.         for (igp = tab->i_head[h]; igp != 0; igp = igp->i_link)
  484.             *ap++ = igp->i_field;
  485.     *ap = 0;
  486.     qsort((char *) ring, tab->i_count, sizeof (char *), igcomp);
  487.     for (ap = ring; *ap != 0; ap++)
  488.         printf("%s\n", *ap);
  489.     return 0;
  490. }
  491.  
  492. /*
  493.  * Compare two names for sorting ignored field list.
  494.  */
  495. igcomp(l, r)
  496.     char **l, **r;
  497. {
  498.  
  499.     return strcmp(*l, *r);
  500. }
  501.